import pandas as pd
import os, re
import numpy as np
import soundfile as sf
from IPython.display import clear_output
import pickle
import librosa
from sklearn.preprocessing import StandardScaler
from tensorflow.keras.utils import to_categorical
import tensorflow as tf
from tensorflow.keras import layers, models
from tensorflow.keras.callbacks import ReduceLROnPlateau, EarlyStopping
from tensorflow.keras.models import load_model
from tensorflow.keras import Model
from sklearn.metrics.pairwise import cosine_similarity
from sklearn.discriminant_analysis import LinearDiscriminantAnalysis as LDA
from sklearn.metrics import det_curve, DetCurveDisplay
import plotly.express as px
import plotly
import matplotlib.pyplot as plt
import plotly.graph_objects as go
long_data_frame_without_postprocess = pd.read_csv("C:/Users/zbugo/Desktop/praktyki_zadania/18/good_data/long_data_frame_without_postprocess.csv")
long_data_frame = pd.read_csv("C:/Users/zbugo/Desktop/praktyki_zadania/18/good_data/long_data_frame.csv")
df_curve_list = []
colors = []
postprocessing_name = []
all_data = []
list_for_FRR_FAR = []
Dane bez postprocessingu.¶
genuine = long_data_frame_without_postprocess[long_data_frame_without_postprocess['genuine']]
impostor = long_data_frame_without_postprocess[~long_data_frame_without_postprocess['genuine']]
data = genuine, impostor
all_data.append(data)
FAR, FRR, thresholds = det_curve(y_true=long_data_frame_without_postprocess['genuine'], y_score=long_data_frame_without_postprocess['score'])
arg_of_best_threshold = np.argmin(np.abs(FAR - FRR))
df_curve = pd.DataFrame({
'False Acceptance Rate': FAR[::10],
'False Rejection Rate': FRR[::10]
}, index=thresholds[::10])
df_curve.index.name = "Thresholds"
df_curve.columns.name = "Rate"
df_curve_list.append(df_curve)
colors.append('blue')
postprocessing_name.append('no postprocess')
FAR_FRR = FAR, FRR
list_for_FRR_FAR.append(FAR_FRR)
Dane z LDA.¶
genuine = long_data_frame[long_data_frame['genuine']]
impostor = long_data_frame[~long_data_frame['genuine']]
data = genuine, impostor
all_data.append(data)
FAR, FRR, thresholds = det_curve(y_true=long_data_frame['genuine'], y_score=long_data_frame['score'])
arg_of_best_threshold = np.argmin(np.abs(FAR - FRR))
y = np.mean(a = np.array(FAR[arg_of_best_threshold], FRR[arg_of_best_threshold]))
x = thresholds[arg_of_best_threshold]
df_curve = pd.DataFrame({
'False Acceptance Rate': FAR[::10],
'False Rejection Rate': FRR[::10]
}, index=thresholds[::10])
df_curve.index.name = "Thresholds"
df_curve.columns.name = "Rate"
df_curve_list.append(df_curve)
colors.append('red')
postprocessing_name.append('lda')
FAR_FRR = FAR, FRR
list_for_FRR_FAR.append(FAR_FRR)
Wykresy.¶
fig, axes = plt.subplots(1, 2, figsize=(18, 8)) # Dwa wykresy obok siebie
for i in range(0, len(all_data)):
col = i # Kolumna (0 lub 1) dla dwóch wykresów obok siebie
# Wybieramy odpowiedni subplot
ax = axes[col]
ax.hist(all_data[i][0]['score'], bins=128, alpha=0.5, label='genuine')
ax.hist(all_data[i][1]['score'], bins=128, alpha=0.5, label='impostor')
ax.set_xlim(-1, 1)
ax.legend()
ax.set_title(postprocessing_name[i])
ax.grid()
plt.show()
Na pierwszy rzut oka trudno ocenić, czy dane po postprocessingu będą łatwiejsze do klasyfikacji niż bez niego. Widzimy jednak różnice na wykresach, szczególnie w rozkładzie dla impostorów, który staje się znacznie bardziej prawoskośny i charakteryzuje się większą kurtozą. Moim zdaniem, oceniając organoleptycznie, histogramy wartości score dla genuine i impostorów po LDA nakładają się w mniejszym stopniu, co może pozwolić modelowi na lepszą klasyfikację, jednak jest to luźne spostrzeżenie. Aby dokładniej ocenić, które dane są lepsze, przejdźmy dalej.
plotly.offline.init_notebook_mode()
# Lista kolorów dla różnych modeli
# Tworzenie pustego wykresu
fig_thresh = go.Figure()
# Iteracyjne dodawanie krzywych do wykresu
for i, df_curve in enumerate(df_curve_list):
legend_group = postprocessing_name[i] # Grupa legendy dla modelu
# Dodanie linii dla FAR (z przypisaną grupą legendy)
fig_thresh.add_trace(go.Scatter(
x=df_curve.index, y=df_curve['False Acceptance Rate'],
mode='lines',
line=dict(color=colors[i]),
name='FAR',
legendgroup=legend_group, # Przypisanie do grupy
showlegend=False # Ukrycie wpisu dla FAR w legendzie
))
# Dodanie linii dla FRR (z przypisaną grupą legendy)
fig_thresh.add_trace(go.Scatter(
x=df_curve.index, y=df_curve['False Rejection Rate'],
mode='lines',
line=dict(color=colors[i]), # Inny styl dla FRR (przerywana linia)
name='FRR',
legendgroup=legend_group, # Przypisanie do grupy
showlegend=False # Ukrycie wpisu dla FRR w legendzie
))
# Znalezienie najlepszego threshold (EER)
arg_of_best_threshold = np.argmin(np.abs(df_curve['False Acceptance Rate'] - df_curve['False Rejection Rate']))
x = df_curve.index[arg_of_best_threshold]
y = np.mean([df_curve['False Acceptance Rate'].iloc[arg_of_best_threshold], df_curve['False Rejection Rate'].iloc[arg_of_best_threshold]])
# Dodanie punktu dla EER (z przypisaną grupą legendy)
fig_thresh.add_trace(go.Scatter(
x=[x], y=[y],
mode='markers',
marker=dict(size=10, color=colors[i]),
name='EER',
legendgroup=legend_group, # Przypisanie do grupy
showlegend=False # Ukrycie wpisu dla EER w legendzie
))
# Dodanie tylko jednego wpisu do legendy dla całego modelu
fig_thresh.add_trace(go.Scatter(
x=[None], y=[None], # Wpis do legendy bez dodawania nowych danych
mode='lines',
line=dict(color=colors[i]),
name=postprocessing_name[i], # Nazwa modelu w legendzie
legendgroup=legend_group, # Przypisanie do tej samej grupy
showlegend=True # Pokaż w legendzie
))
# Dostosowanie osi i tytułu
fig_thresh.update_layout(
title="FRR, FAR EER for types of post-processing",
xaxis_title="Thresholds",
width=1200,
height=600
)
# Wyświetlenie wykresu
fig_thresh.show()
Na wykresie można odczytać wartości FAR i FRR dla różnych wartości thresholdu, co pozwala znaleźć kompromis w postaci EER, czyli punktu przecięcia się krzywych FAR i FRR. Im mniejsza wartość EER, tym lepiej. Zaskakujące jest, że dane po LDA uzyskują gorszy wynik – wartość EER modelu z tymi danymi jest większa (około 0.75) niż dla danych bez postprocessingu (około 0.69).
plotly.offline.init_notebook_mode()
fig = go.Figure()
for i in range(0,len(list_for_FRR_FAR)):
FAR, FRR = list_for_FRR_FAR[i]
fig.add_trace(go.Scatter(x=FAR, y=FRR, name=postprocessing_name[i], mode='lines'))
fig.update_layout(
title='Krzywa DET',
xaxis_title='FAR',
yaxis_title='FRR',
width=1200,
height=600
)
fig.update_xaxes(range=[0, 0.35])
fig.update_yaxes(range=[0, 0.55])
fig.show()